package com.sz.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

public class SortRunThread {


    public static void main(String[] args) {

        ny();

        int n = 10;
//
//        List<Thread> threads = new ArrayList<>();
//
//        for (int i = 0; i < n; i++) {
//            MyThread thread = new MyThread(i);
//            threads.add(thread);
//            if (i > 0){
//                thread.setThread(threads.get(i-1));
//            }
//            thread.start();
//        }
//
//
//        CountDownLatch countDownLatch = new CountDownLatch(n);
//
//        for (int i = 0; i < n; i++) {
//
//        }

        List<CountDownLatch> countDownLatchList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (i > 0){
                System.out.println("SortRunThread.main countDownLatch i "+i);
                CountDownLatch countDownLatch = new CountDownLatch(i);
                countDownLatchList.add(countDownLatch);
            }
        }

        for (int i = 0; i < n; i++) {
            MyThread2 thread2 = new MyThread2(countDownLatchList,n,i);
            thread2.start();
        }

//        List<FutureTask<Integer>> futureTasks = new ArrayList<>();
//        List<MyCallable<Integer>> callables = new ArrayList<>();
//        for (int i = 0; i < n; i++) {
//            MyCallable<Integer> myCallable = new MyCallable<>(i);
//            futureTasks.add(new FutureTask<>(myCallable));
//            callables.add(myCallable);
//        }
//
//        for (int i = 0; i < n; i++) {
//            callables.get(i).setFutureTasks(futureTasks);
//        }
//
//        for (int i = 0; i < n; i++) {
////            new Thread(futureTasks.get(i)).start();
//        }
//
//
//        ExecutorService executorService = Executors.newSingleThreadExecutor();
//        for (int i = 0; i < n; i++) {
//            executorService.submit(callables.get(i));
//        }


        AtomicBoolean t1Runned = new AtomicBoolean(false);
        Object lock = new Object();
        Thread thread2 = new Thread(()->{
            synchronized (lock){
                while (!t1Runned.get()){
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("SortRunThread.main t2");
                }
            }
        });
        thread2.start();

        Thread thread1 = new Thread(()->{
           synchronized (lock){
               t1Runned.set(true);
               System.out.println("SortRunThread.main t1");

               lock.notifyAll();
           }
        });

        thread1.start();

    }

    private static class MyCallable<V> implements Callable<V>{
        private int i;
        private List<FutureTask<Integer>> futureTasks;

        public MyCallable(int i) {
            this.i = i;
        }

        public List<FutureTask<Integer>> getFutureTasks() {
            return futureTasks;
        }

        public void setFutureTasks(List<FutureTask<Integer>> futureTasks) {
            this.futureTasks = futureTasks;
        }

        @Override
        public V call() throws Exception {
//            if (i > 0){
//                futureTasks.get(i-1).get();
//            }
            System.out.println("MyCallable.call "+ i);
            return null;
        }


    }
    /**
     * CountDownLatch 模拟串行
     */
    private static class MyThread2 extends Thread{

        private List<CountDownLatch> countDownLatchList;

        private int sum;
        private int i;

        public MyThread2(List<CountDownLatch> countDownLatchList, int sum, int i) {
            this.countDownLatchList = countDownLatchList;
            this.sum = sum;
            this.i = i;
        }

        @Override
        public void run() {

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (i > 0){
                try {
                    countDownLatchList.get(i-1).await();

                    System.out.println("MyThread2.run "+i + "start");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                System.out.println("MyThread2.run "+i + "start");

            }

            for (int i1 = i; i1 < countDownLatchList.size(); i1++) {
                countDownLatchList.get(i1).countDown();
            }





        }
    }

    /**
     * join 模拟串行
     */
    private static class MyThread extends Thread{

        private Thread thread;

        private int i;

        public MyThread(int i) {
            this.i = i;
        }

        public Thread getThread() {
            return thread;
        }

        public void setThread(Thread thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            try {

                Random random = new Random();
                int sleepTime = random.nextInt(800);
                Thread.sleep(sleepTime);

                if (this.thread != null){
                    this.thread.join();
                }

                System.out.println("MyThread.run "+ this.i);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void ny(){
        String str="haha";
        System.out.println("SortRunThread.ny str "+str.hashCode());
        new Thread() {
            @Override
            public void run() {
//                str= "";

                System.out.println("SortRunThread.ny str run "+str.hashCode());

                System.out.println(str);
            }
        }.start();

    }
}
